/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.persistence.manager;

import java.io.Serializable;
import java.util.List;

import com.genia.toolbox.basics.bean.IterableIterator;
import com.genia.toolbox.persistence.bean.Persistable;
import com.genia.toolbox.persistence.bean.QueryParameters;
import com.genia.toolbox.persistence.criteria.Criteria;
import com.genia.toolbox.persistence.criteria.CriteriaResult;
import com.genia.toolbox.persistence.exception.PersistenceException;

/**
 * This interface represents the generic persistent manager for saving, updating
 * or deleting an instance of persistable object.
 */
public interface PersistenceManager
{

  /**
   * This method deletes an object.
   * 
   * @param object
   *          The object to delete
   * @throws PersistenceException
   *           if any problems occur during persistence process
   */
  public void delete(Persistable<? extends Serializable> object)
      throws PersistenceException;



  /**
   * flush eventual cached elements.
   */
  public abstract void clear();



  /**
   * This method deletes an object if it is persistent, otherwise do nothing.
   * 
   * @param object
   *          The object to delete
   * @throws PersistenceException
   *           if any problems occur during persistence process
   */
  public void deleteIfPersistent(Persistable<? extends Serializable> object)
      throws PersistenceException;



  /**
   * This method returns the results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @return the list of <code>CriteriaResult</code> that represents the
   *         result of the query
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> List<CriteriaResult<MAINTYPE>> find(Criteria<MAINTYPE> criteria)
      throws PersistenceException;



  /**
   * This method returns the results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @param parameters
   *          the parameters of this search
   * @return the list of <code>CriteriaResult</code> that represents the
   *         result of the query
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> List<CriteriaResult<MAINTYPE>> find(Criteria<MAINTYPE> criteria, QueryParameters parameters)
      throws PersistenceException;



  /**
   * This method returns the unique result of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria.
   * @param criteria
   *          the criteria that describes the query
   * @return the <code>CriteriaResult</code> that represents the result of the
   *         query if there is an unique record, null if there is no record and throws a {@link ResultIsNotUniqueException} if there is more than one record
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> CriteriaResult<MAINTYPE> findUnique(Criteria<MAINTYPE> criteria)
      throws PersistenceException;



  /**
   * This method get an persited object given its class and identifier.
   * 
   * @param <IDENTIFIER>
   *          The type of the identifier
   * @param <TYPE>
   *          The type of the object to retrieve
   * @param type
   *          The class of the object to retrieve
   * @param identifier
   *          The identifier of the object to retrieve
   * @return the object of class <code>type</code> with the identifier
   *         <code>identifier</code> or <code>null</code> if no such object
   *         exists
   */
  public <IDENTIFIER extends Serializable, TYPE extends Persistable<IDENTIFIER>> TYPE get(Class<TYPE> type, IDENTIFIER identifier);



  /**
   * This methods return all the persisted objects of a given type.
   * 
   * @param <TYPE>
   *          the type of the objects to retrieve
   * @param type
   *          the class of the objects to retrieve
   * @return the list of all objects of the given type
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <TYPE> List<TYPE> getAll(Class<TYPE> type)
      throws PersistenceException;



  /**
   * This methods return a new <code>Criteria</code> for the object of type
   * <code>mainType</code>.
   * 
   * @param <MAINTYPE>
   *          The main type of the criteria
   * @param mainType
   *          The class of the main type of the criteria
   * @return a <code>Criteria</code> to describe a new query
   */
  public <MAINTYPE> Criteria<MAINTYPE> getCriteria(Class<MAINTYPE> mainType);



  /**
   * returns the {@link CrossSessionManager} to use with this
   * {@link PersistenceManager}.
   * 
   * @return the {@link CrossSessionManager} to use with this
   *         {@link PersistenceManager}
   */
  public abstract CrossSessionManager getCrossSessionManager();



  /**
   * This method returns the <code>FieldManager</code> to use with this
   * persistent manager.
   * 
   * @return the <code>FieldManager</code> to use with this persistent manager
   */
  public FieldManager getFieldManager();



  /**
   * This method returns the <code>OrderManager</code> to use with this
   * persistent manager.
   * 
   * @return the <code>OrderManager</code> to use with this persistent manager
   */
  public OrderManager getOrderManager();



  /**
   * This method returns the <code>RestrictionsManager</code> to use with this
   * persistent manager.
   * 
   * @return the <code>RestrictionsManager</code> to use with this persistent
   *         manager
   */
  public RestrictionsManager getRestrictionsManager();



  /**
   * This method iterates over the results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @return the list of <code>CriteriaResult</code> that represents the
   *         result of the query
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> IterableIterator<CriteriaResult<MAINTYPE>> iterate(Criteria<MAINTYPE> criteria)
      throws PersistenceException;



  /**
   * This method iterates over the results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @param parameters
   *          the parameters of this search
   * @return the list of <code>CriteriaResult</code> that represents the
   *         result of the query
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> IterableIterator<CriteriaResult<MAINTYPE>> iterate(Criteria<MAINTYPE> criteria, QueryParameters parameters)
      throws PersistenceException;



  /**
   * This method saves a new object.
   * 
   * @param object
   *          The object to save
   * @throws PersistenceException
   *           if any problems occur during persistence process
   */
  public void save(Persistable<? extends Serializable> object)
      throws PersistenceException;



  /**
   * This method saves a new object or update an already persistent object. This
   * method should be avoided as much as possible. Finding if an object is
   * persistent or not is tedious and error prone, unexpected comportment can
   * arrise.
   * 
   * @param object
   *          The object to save or update
   * @throws PersistenceException
   *           if any problems occur during persistence process
   */
  public void saveOrUpdate(Persistable<? extends Serializable> object)
      throws PersistenceException;



  /**
   * This method returns the main results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @return the list of result
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> List<MAINTYPE> simpleFind(Criteria<MAINTYPE> criteria)
      throws PersistenceException;



  /**
   * This method returns the main results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @param parameters
   *          the parameters of this search
   * @return the list of result
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> List<MAINTYPE> simpleFind(Criteria<MAINTYPE> criteria, QueryParameters parameters)
      throws PersistenceException;



  /**
   * This method returns the unique main results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @return the unique result if there is an unique record, null if there is no record and throws a {@link ResultIsNotUniqueException} if there is more than one record
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> MAINTYPE simpleFindUnique(Criteria<MAINTYPE> criteria)
      throws PersistenceException;



  /**
   * This method iterates over the main results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @return the list of result
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> IterableIterator<MAINTYPE> simpleIterate(Criteria<MAINTYPE> criteria)
      throws PersistenceException;



  /**
   * This method iterates over the main results of a criteria.
   * 
   * @param <MAINTYPE>
   *          the main type of the criteria
   * @param criteria
   *          the criteria that describes the query
   * @param parameters
   *          the parameters of this search
   * @return the list of result
   * @throws PersistenceException
   *           when there is a problem with the persisence layer
   */
  public <MAINTYPE> IterableIterator<MAINTYPE> simpleIterate(Criteria<MAINTYPE> criteria, QueryParameters parameters)
      throws PersistenceException;



  /**
   * This method updates an object.
   * 
   * @param object
   *          The object to update
   * @throws PersistenceException
   *           if any problems occur during persistence process
   */
  public void update(Persistable<? extends Serializable> object)
      throws PersistenceException;
}
